This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

library(lme4)
library(ggplot2)
library(plotrix)
library(visreg)
library(stringr)
library(dplyr)
library(ggpubr)
library(gridExtra)
lasso_output_data <- data.frame(read.csv("/Users/noa/Workspace/lasso_positions_sampling_results/ls_c.csv",header = TRUE, na.strings = ""))
data_source = data.frame(read.csv("/Users/noa/Workspace/data/sampled_datasets.csv",header = TRUE, na.strings = ""))
lasso_output_data$relative_path = str_replace_all(lasso_output_data$dataset_id,'(/groups/pupko/noaeker/data/ABC_DR/)|(/ref_msa.aa.phy)',"")
data_only_lasso= merge(lasso_output_data,data_source,by.x="relative_path",by.y="path")
if (nrow(data_only_lasso)<nrow(lasso_output_data))
{print("Problem in matching path names")
  cat("nrow data=",nrow(data), "nrow lasso=",nrow(data_only_lasso))
}



#spr_new<-merge(good_datasets, spr_new, by = "dataset_id")
#test<-spr_new %>% group_by(dataset_id) %>% count(dataset_id)
print(summary(data_only_lasso$mad))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0830  0.1390  0.1830  0.1894  0.2230  0.3480 
print(summary(data_only_lasso$divergence))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.3357  0.9365  1.4852  1.6892  2.2875  5.3054 
print(summary(data_only_lasso$lasso_test_mse))
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
     1.7     63.4    279.3   3630.7   1516.7 590641.5 

General statistics on the data

file_name_and_source_lasso=data_only_lasso[!duplicated(data_only_lasso[ , c("db","dataset_id")]),]

table(file_name_and_source_lasso$db)

Selectome 
       54 
print(summary(data_only_lasso$n_loci))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    977    1884    2368    2424    2815    4593 

Good functions

plot.hist<-function(x,main,xlab, title_size=13, text_size=12)
{
  qplot(x,
      geom="histogram",
      main = main, 
      xlab = xlab,
      fill=I("blue"), 
      col=I("red"), 
      alpha=I(.2),
      #xlim=c(20,50)
      ) +  theme(plot.title = element_text(hjust = 0.5,size=title_size)) +theme(text = element_text(size = text_size)) 

}

lmp <- function (modelobject) {
    if (class(modelobject) != "lm") stop("Not an object of class 'lm' ")
    f <- summary(modelobject)$fstatistic
    p <- pf(f[1],f[2],f[3],lower.tail=F)
    attributes(p) <- NULL
    return(p)
}

simple.regression<-function(x,y,main,xlab, ylab,cex=1.0,resid_plot=FALSE)
{linearMod <- lm((y) ~ x)
print(main)
print(summary(linearMod)) 
r.squared <- summary(linearMod)$r.squared
    p.val <- lmp(linearMod)
if (resid_plot==TRUE)
{plot(fitted(linearMod),resid(linearMod), main =main,xlab=xlab)
abline(0, 0)
}
    
    return(c(r.squared,p.val))
}

Lasso example using optimized branch lengths and chosen_size random trees

example_MSA_data_lasso = data_only_lasso%>%filter(job_id==10)
print(example_MSA_data_lasso)

training_optimized_chosen_size_example_data = 
  data.frame(read.csv("/Users/noa/Workspace/lasso_positions_sampling_results/training_sitelh_df_prediction.csv",header = TRUE, na.strings = ""))
names(training_optimized_chosen_size_example_data)[2:3]=c("training_true_val","training_predicted_val")
test_optimized_chosen_size_example_data = 
  data.frame(read.csv("/Users/noa/Workspace/lasso_positions_sampling_results/test_sitelh_df_prediction.csv",header = TRUE, na.strings = ""))
names(test_optimized_chosen_size_example_data)[2:3]=c("test_true_val","test_predicted_val")



chosen_size=800
example_MSA_data_lasso_chosen_size= example_MSA_data_lasso%>% filter(actucal_training_size==chosen_size)
example_MSA_data_lasso_chosen_size_optimized = example_MSA_data_lasso%>% filter(actucal_training_size==chosen_size, brlen_generator=="optimized")
print(dplyr::select(example_MSA_data_lasso_chosen_size,"dataset_id","brlen_generator","job_id","curr_msa_version_folder","n_seq", "db","number_loci_chosen","n_loci","alpha","lasso_training_R.2", "lasso_test_R.2","sample_pct", "lasso_training_spearmanr", "lasso_test_spearmanr"))

print(dplyr::select(example_MSA_data_lasso_chosen_size_optimized,"dataset_id","job_id","curr_msa_version_folder","n_seq", "db","number_loci_chosen","n_loci","alpha","lasso_training_R.2", "lasso_test_R.2","sample_pct", "lasso_training_spearmanr", "lasso_test_spearmanr"))
training_optimized_chosen_size_example_data["training delta ll"] =training_optimized_chosen_size_example_data["training_true_val"]-training_optimized_chosen_size_example_data["training_predicted_val"]
test_optimized_chosen_size_example_data["test delta ll"] =test_optimized_chosen_size_example_data["test_true_val"]-test_optimized_chosen_size_example_data["test_predicted_val"]
print(training_optimized_chosen_size_example_data[,c("training_predicted_val","training_true_val","training delta ll")])
print(test_optimized_chosen_size_example_data[,c("test_predicted_val","test_true_val","test delta ll")])

p0<-simple.regression(training_optimized_chosen_size_example_data$training_true_val,training_optimized_chosen_size_example_data$training_predicted_val,"Training set predicted log likelihood vs true log likelihood","Training set true log likelihood","Training set predicted log likelihood")
[1] "Training set predicted log likelihood vs true log likelihood"

Call:
lm(formula = (y) ~ x)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.5921  -1.6414  -0.0004   1.4776   9.9491 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -3.285e+01  1.114e+01   -2.95  0.00327 ** 
x            9.984e-01  5.409e-04 1845.85  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.901 on 798 degrees of freedom
Multiple R-squared:  0.9998,    Adjusted R-squared:  0.9998 
F-statistic: 3.407e+06 on 1 and 798 DF,  p-value: < 2.2e-16

p1<-simple.regression(test_optimized_chosen_size_example_data$test_true_val,test_optimized_chosen_size_example_data$test_predicted_val,"Test set predicted log likelihood vs true log likelihood","Test set true log likelihood","Test set predicted log likelihood",cex=1)
[1] "Test set predicted log likelihood vs true log likelihood"

Call:
lm(formula = (y) ~ x)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.7685  -2.1954   0.0862   1.8887  15.1095 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -54.099352  36.540325  -1.481    0.142    
x             0.997388   0.001773 562.489   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.41 on 98 degrees of freedom
Multiple R-squared:  0.9997,    Adjusted R-squared:  0.9997 
F-statistic: 3.164e+05 on 1 and 98 DF,  p-value: < 2.2e-16

g0<-ggplot(training_optimized_chosen_size_example_data,aes(training_true_val, training_predicted_val)) + 
  geom_smooth(method='lm')+xlab("true log likelihood")+ylab("predicted log likelihood ")+geom_point()+ labs(title="Training set predicted log likelihood vs true log likelihood")+theme(plot.title = element_text(hjust = 0.5)) +annotate("text", x=-20300, y=-19800, label= sprintf("R^2 = %.4f",p0[1]),size=4) +annotate("text", x=-20300, y=-19950, label= "p value < 2e-324",size=4) 

g1<-ggplot(test_optimized_chosen_size_example_data,aes(test_true_val, test_predicted_val)) + 
  geom_smooth(method='lm')+xlab("true log likelihood")+ylab("predicted log likelihood ")+geom_point()+ labs(title="Test set predicted log likelihood vs true log likelihood")+theme(plot.title = element_text(hjust = 0.5)) +annotate("text", x=-20300, y=-19800, label= sprintf("R^2 = %.4f",p1[1])) +annotate("text", x=-20300, y=-19950, label= sprintf("p value = %.2e",p1[2])) 


fig<-ggarrange(g0, g1, hjust=-1,vjust=1, heights=c(2,2),common.legend=TRUE, 
          labels = c("A", "B"),
          ncol = 1, nrow =2)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
fig

NA
NA
NA
NA
boxplot(test_optimized_chosen_size_example_data["test delta ll"])

summary(test_optimized_chosen_size_example_data["test delta ll"])
 test delta ll      
 Min.   :-15.00067  
 1st Qu.: -1.58644  
 Median :  0.06853  
 Mean   :  0.28275  
 3rd Qu.:  2.14509  
 Max.   : 11.48662  
print(test_optimized_chosen_size_example_data)
NA

Lasso problematic datasets

print( data_only_lasso[data_only_lasso$lasso_test_R.2<0.9,c("brlen_generator","actucal_training_size","n_seq","n_loci","sample_pct","lasso_test_R.2", "lasso_training_R.2", "lasso_training_spearmanr","number_loci_chosen")])
NA

Example MSA Lasso statistics

library(ggpubr)

dplyr::select(example_MSA_data_lasso,actucal_training_size,brlen_generator,lasso_test_R.2,lasso_test_spearmanr,sample_pct,number_loci_chosen)
dplyr::select(example_MSA_data_lasso%>%filter(actucal_training_size==chosen_size),actucal_training_size,brlen_generator,lasso_test_R.2,lasso_test_spearmanr,sample_pct,number_loci_chosen)


g0<-ggplot(example_MSA_data_lasso, aes(x=as.factor(actucal_training_size),fill=brlen_generator, y=lasso_test_R.2))+
     geom_bar(stat="identity",position=position_dodge()) +
  xlab("Training size")+ylab("R squared ")+theme(axis.title=element_text(size=10))+guides(fill=guide_legend(title="Branch length distribution"))+ggtitle("Test set R squared vs. training size")+ theme(plot.title = element_text(hjust = 0.5)) +coord_cartesian(ylim = c(0.55, 1))


ggplot(example_MSA_data_lasso, aes(x=as.factor(actucal_training_size),fill=brlen_generator, y=example_MSA_data_lasso$lasso_test_mse))+
     geom_bar(stat="identity",position=position_dodge()) +
  xlab("Training size")+ylab("MSE ")+theme(axis.title=element_text(size=10))+guides(fill=guide_legend(title="Branch length distribution"))+ggtitle("Test set R squared vs. training size")+ theme(plot.title = element_text(hjust = 0.5))



 g2<-ggplot(example_MSA_data_lasso, aes(x=as.factor(actucal_training_size),fill=brlen_generator, y=sample_pct))+ labs(color = "Branch length distribution")+
     geom_bar(stat="identity",position=position_dodge()) +
   xlab("Training size")+ylab("% Positions")+ theme(axis.title=element_text(size=10),)+guides(fill=guide_legend(title="Branch length distribution"))+ggtitle("Percentage of positions chosen by Lasso vs. training size" )+scale_y_continuous(labels = scales::percent)+ theme(plot.title = element_text(hjust = 0.5)) 

ggarrange(g0, g2, hjust=-1,vjust=0, heights=c(2,2),common.legend=TRUE, 
          labels = c("A", "B"),
          ncol = 1, nrow =2)



plot(example_MSA_data_lasso$lasso_test_mse, example_MSA_data_lasso$lasso_test_R.2)

NA
NA
NA
NA
NA
print(example_MSA_data_lasso[,c("brlen_generator","n_loci","number_loci_chosen")])
lasso_unique<-unique(dplyr::select(data_only_lasso,dataset_id,n_loci,sample_pct))
plot(lasso_unique$n_loci,lasso_unique$sample_pct )

Figure 6 - Lasso on 50 MSAs only 3200


chosen_size = 3200
data_lasso_only_chosen_size = data_only_lasso[data_only_lasso$actucal_training_size==chosen_size,]

lasso.chosen_size.summary = data_lasso_only_chosen_size %>%
group_by() %>%
summarise(across(.cols=c(lasso_test_R.2,lasso_test_spearmanr,sample_pct), .fns= list(Median=median), na.rm= TRUE),.groups = "drop")

print(lasso.chosen_size.summary)

lasso.chosen_size.summary.per.brlen = data_lasso_only_chosen_size %>%
group_by(actucal_training_size,brlen_generator ) %>%
summarise(across(.cols=c(lasso_test_R.2,lasso_test_spearmanr,sample_pct), .fns= list(Median=median), na.rm= TRUE),.groups = "drop")
print(lasso.chosen_size.summary.per.brlen)
    
    
#Figure 6
g0<-ggplot(data_lasso_only_chosen_size,aes(lasso_test_R.2,fill=brlen_generator))+ 
     geom_histogram()+
    labs(title="Lasso test set Pearson R squared")+xlab("Pearson R squared")+ labs(fill= "Branch length distribution")+
  theme(plot.title = element_text(hjust = 0.5)) 
g2<- ggplot(data_lasso_only_chosen_size,aes(sample_pct,fill=brlen_generator))+ 
     geom_histogram()+
    labs(title="Percentage of positions chosen by Lasso")+xlab("% positions")+ labs(fill = "Branch length distribution")+
  theme(plot.title = element_text(hjust = 0.5))+theme(legend.position = "none") 



ggarrange(g0, g2,hjust=-1,vjust=0,common.legend=TRUE,align="h",
          labels = c("A", "B"),
          ncol = 1, nrow =2)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

NA
NA

Figure 4 or table2 - results on 50 MSAs


per.brlen.size = dplyr::select(data_only_lasso,actucal_training_size,brlen_generator,lasso_test_R.2,sample_pct) %>%
group_by(actucal_training_size,brlen_generator) %>%
summarise(across(.fns= list(Median=median), na.rm= TRUE),.groups = "drop")
print(per.brlen.size)


per.brlen.size.mse = dplyr::select(data_only_lasso,lasso_test_mse,actucal_training_size,brlen_generator) %>%
group_by(actucal_training_size,brlen_generator) %>%
summarise(across(.fns= list(Median=median), na.rm= TRUE),.groups = "drop")
print(per.brlen.size.mse )

optimized_mse = filter(per.brlen.size.mse, brlen_generator=="optimized")
optimized_R2=filter(per.brlen.size, brlen_generator=="optimized")

plot(optimized_mse$actucal_training_size, optimized_mse$lasso_test_mse_Median,type="b", xlab="Training size", ylab ="Median test MSE",title="Median test MSE vs. training size for optimized branch-length")


g00<-ggplot(optimized_mse,aes(x=actucal_training_size,y=lasso_test_mse_Median))+geom_line()+geom_point(data=optimized_mse,aes(x=actucal_training_size,y=lasso_test_mse_Median))+xlab("Training size")+ylab("Median test MSE")+ggtitle("Median test MSE vs. training size for optimized branch-lengths")+ theme(plot.title = element_text(hjust = 0.5),axis.text=element_text(size=11),axis.title=element_text(size=11)
) 

g01<-ggplot(optimized_R2e,aes(x=actucal_training_size,y=lasso_test_R.2_Median))+geom_line()+geom_point(data=optimized_R2,aes(x=actucal_training_size,y=lasso_test_R.2_Median))+xlab("Training size")+ylab("Median test R2")+ggtitle("Median test MSE vs. training size for optimized branch-lengths")+ theme(plot.title = element_text(hjust = 0.5),axis.text=element_text(size=11),axis.title=element_text(size=11)






#ggarrange(g00, g01,g02,hjust=-1,vjust=0.5, 
#          labels = c("A", "B","C"),
 #         ncol = 1, nrow =3)




g0<-ggplot(data_only_lasso,aes(x=as.factor(actucal_training_size),color=brlen_generator, y=lasso_test_R.2))+ 
Error: unexpected symbol in:
"
g0"

Statistical analysis of test MSE vs training size and MSA metrics

library(rstatix)
library(nlme)
library(multcomp)


data_only_lasso$training_size_factor = as.factor(data_only_lasso$actucal_training_size)
data_only_lasso$n_loci.1000=data_only_lasso$n_loci/1000
data_exponential<-data_only_lasso %>% filter(brlen_generator=="exponential")
data_optimized<-data_only_lasso %>% filter(brlen_generator=="optimized")
data_uniform<-data_only_lasso %>% filter(brlen_generator=="uniform")
model<-lme(lasso_test_mse~training_size_factor+divergence+mad+gap_pct+n_loci.1000,random=~1|dataset_id, data=data_uniform)
plot(model.uniform)
qqnorm(model.uniform$residuals)
print(summary(model.uniform))
print(intervals(model.uniform,which = "fixed"))
summary(glht(model=model.uniform, linfct=mcp(training_size_factor =c("training_200 - training_100 >= 0","training_400 - training_200 >= 0","training_800 - training_400 >= 0","training_1600 - training_800 >= 0","training_3200 - training_1600 >= 0")),test = adjusted(type = "bonferroni")))

uniform

data_uniform<-data_only_lasso %>% filter(brlen_generator=="uniform")
data_uniform$training_size_factor = as.factor(paste('training_', data_uniform$training_size_factor,sep = ""))
model.uniform<-lme(lasso_test_mse~training_size_factor+divergence+mad+gap_pct+n_loci.1000,random=~1|dataset_id, data=data_uniform)
plot(model.uniform)

qqnorm(model.uniform$residuals)

print(summary(model.uniform))
Linear mixed-effects model fit by REML
  Data: data_uniform 

Random effects:
 Formula: ~1 | dataset_id
        (Intercept) Residual
StdDev:    4924.748 12903.35

Fixed effects:  lasso_test_mse ~ training_size_factor + divergence + mad + gap_pct +      n_loci.1000 
 Correlation: 
                                  (Intr) t___16 t___20 t___32 t___40 t___80 dvrgnc mad    gp_pct
training_size_factortraining_1600 -0.188                                                        
training_size_factortraining_200  -0.188  0.500                                                 
training_size_factortraining_3200 -0.188  0.500  0.500                                          
training_size_factortraining_400  -0.188  0.500  0.500  0.500                                   
training_size_factortraining_800  -0.188  0.500  0.500  0.500  0.500                            
divergence                        -0.427  0.000  0.000  0.000  0.000  0.000                     
mad                               -0.697  0.000  0.000  0.000  0.000  0.000  0.263              
gap_pct                           -0.091  0.000  0.000  0.000  0.000  0.000 -0.499 -0.144       
n_loci.1000                       -0.733  0.000  0.000  0.000  0.000  0.000  0.329  0.301 -0.147

Standardized Within-Group Residuals:
         Min           Q1          Med           Q3          Max 
-2.328850562 -0.278646376 -0.004173891  0.183514337 13.367424993 

Number of Observations: 324
Number of Groups: 54 
print(intervals(model.uniform,which = "fixed"))
Approximate 95% confidence intervals

 Fixed effects:
                                       lower       est.     upper
(Intercept)                       -14136.725  -1155.618 11825.488
training_size_factortraining_1600 -17462.917 -12573.505 -7684.093
training_size_factortraining_200  -13612.376  -8722.964 -3833.551
training_size_factortraining_3200 -17537.171 -12647.759 -7758.346
training_size_factortraining_400  -15989.228 -11099.816 -6210.403
training_size_factortraining_800  -17026.671 -12137.258 -7247.846
divergence                          2015.629   4493.347  6971.065
mad                               -52021.528 -16266.467 19488.594
gap_pct                           -36520.822 -20831.781 -5142.740
n_loci.1000                         4509.922   7428.200 10346.479
attr(,"label")
[1] "Fixed effects:"
summary(glht(model=model.uniform, linfct=mcp(training_size_factor =c("training_200 - training_100 >= 0","training_400 - training_200 >= 0","training_800 - training_400 >= 0","training_1600 - training_800 >= 0","training_3200 - training_1600 >= 0")),test = adjusted(type = "bonferroni")))

     Simultaneous Tests for General Linear Hypotheses

Multiple Comparisons of Means: User-defined Contrasts


Fit: lme.formula(fixed = lasso_test_mse ~ training_size_factor + divergence + 
    mad + gap_pct + n_loci.1000, data = data_uniform, random = ~1 | 
    dataset_id)

Linear Hypotheses:
                                   Estimate Std. Error z value  Pr(<z)   
training_200 - training_100 >= 0   -8722.96    2483.25  -3.513 0.00113 **
training_400 - training_200 >= 0   -2376.85    2483.25  -0.957 0.66510   
training_800 - training_400 >= 0   -1037.44    2483.25  -0.418 0.95169   
training_1600 - training_800 >= 0   -436.25    2483.25  -0.176 0.99144   
training_3200 - training_1600 >= 0   -74.25    2483.25  -0.030 0.99803   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Adjusted p values reported -- single-step method)
plot(data_only_lasso$n_loci,data_only_lasso$lasso_test_mse**0.5)

hist(data_only_lasso[data_only_lasso$brlen_generator=="exponential",]$lasso_test_mse, breaks=100)

boxplot(data_only_lasso[data_only_lasso$brlen_generator=="exponential",]$lasso_test_mse)

print(summary(data_only_lasso[data_only_lasso$brlen_generator=="exponential" & data_only_lasso$actucal_training_size==3200,]$lasso_test_mse))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.48  110.79  214.10  979.79  710.08 8892.41 
print(summary(data_only_lasso[data_only_lasso$brlen_generator=="exponential" & data_only_lasso$actucal_training_size==3200,]$lasso_test_R.2))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.8277  0.9902  0.9979  0.9881  0.9991  0.9997 

optimized

data_optimized<-data_only_lasso %>% filter(brlen_generator=="optimized")
data_optimized$training_size_factor = as.factor(paste('training_', data_optimized$training_size_factor,sep = ""))
model.optimized<-lme(lasso_test_mse~training_size_factor+divergence+mad+gap_pct+n_loci.1000,random=~1|dataset_id, data=data_optimized)
print(summary(model.optimized))
Linear mixed-effects model fit by REML
  Data: data_optimized 

Random effects:
 Formula: ~1 | dataset_id
        (Intercept) Residual
StdDev:    99.61194 147.2473

Fixed effects:  lasso_test_mse ~ training_size_factor + divergence + mad + gap_pct +      n_loci.1000 
 Correlation: 
                                  (Intr) t___16 t___20 t___32 t___40 t___80 dvrgnc mad    gp_pct
training_size_factortraining_1600 -0.135                                                        
training_size_factortraining_200  -0.135  0.500                                                 
training_size_factortraining_3200 -0.135  0.500  0.500                                          
training_size_factortraining_400  -0.135  0.500  0.500  0.500                                   
training_size_factortraining_800  -0.135  0.500  0.500  0.500  0.500                            
divergence                        -0.433  0.000  0.000  0.000  0.000  0.000                     
mad                               -0.708  0.000  0.000  0.000  0.000  0.000  0.263              
gap_pct                           -0.092  0.000  0.000  0.000  0.000  0.000 -0.499 -0.144       
n_loci.1000                       -0.744  0.000  0.000  0.000  0.000  0.000  0.329  0.301 -0.147

Standardized Within-Group Residuals:
         Min           Q1          Med           Q3          Max 
-3.093391833 -0.249261687  0.002988116  0.187539098  9.051032170 

Number of Observations: 324
Number of Groups: 54 
plot(model.optimized)

print(intervals(model.optimized,which = "fixed"))
Approximate 95% confidence intervals

 Fixed effects:
                                        lower       est.      upper
(Intercept)                         -65.98936  140.32821  346.64578
training_size_factortraining_1600  -291.51870 -235.72290 -179.92710
training_size_factortraining_200   -200.71387 -144.91807  -89.12227
training_size_factortraining_3200  -294.19936 -238.40356 -182.60776
training_size_factortraining_400   -257.55783 -201.76202 -145.96622
training_size_factortraining_800   -278.59913 -222.80332 -167.00752
divergence                           12.76796   52.74287   92.71778
mad                               -1132.50329 -555.63978   21.22372
gap_pct                            -440.84519 -187.72200   65.40119
n_loci.1000                          40.74230   87.82510  134.90790
attr(,"label")
[1] "Fixed effects:"
summary(glht(model=model.optimized, linfct=mcp(training_size_factor =c("training_200 - training_100 >= 0","training_400 - training_200 >= 0","training_800 - training_400 >= 0","training_1600 - training_800 >= 0","training_3200 - training_1600 >= 0")),test = adjusted(type = "bonferroni")))

     Simultaneous Tests for General Linear Hypotheses

Multiple Comparisons of Means: User-defined Contrasts


Fit: lme.formula(fixed = lasso_test_mse ~ training_size_factor + divergence + 
    mad + gap_pct + n_loci.1000, data = data_optimized, random = ~1 | 
    dataset_id)

Linear Hypotheses:
                                   Estimate Std. Error z value Pr(<z)    
training_200 - training_100 >= 0   -144.918     28.338  -5.114 <0.001 ***
training_400 - training_200 >= 0    -56.844     28.338  -2.006  0.109    
training_800 - training_400 >= 0    -21.041     28.338  -0.743  0.807    
training_1600 - training_800 >= 0   -12.920     28.338  -0.456  0.941    
training_3200 - training_1600 >= 0   -2.681     28.338  -0.095  0.996    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Adjusted p values reported -- single-step method)

exponential

data_exponential<-data_only_lasso %>% filter(brlen_generator=="exponential")
data_exponential$training_size_factor = as.factor(paste('training_', data_exponential$training_size_factor,sep = ""))
model.exponential<-lme(lasso_test_mse~training_size_factor+divergence+mad+gap_pct+n_loci.1000,random=~1|dataset_id, data=data_exponential)
plot(model.exponential)

print(summary(model.exponential))
Linear mixed-effects model fit by REML
  Data: data_exponential 

Random effects:
 Formula: ~1 | dataset_id
        (Intercept) Residual
StdDev:    2539.826 32238.76

Fixed effects:  lasso_test_mse ~ training_size_factor + divergence + mad + gap_pct +      n_loci.1000 
 Correlation: 
                                  (Intr) t___16 t___20 t___32 t___40 t___80 dvrgnc mad    gp_pct
training_size_factortraining_1600 -0.247                                                        
training_size_factortraining_200  -0.247  0.500                                                 
training_size_factortraining_3200 -0.247  0.500  0.500                                          
training_size_factortraining_400  -0.247  0.500  0.500  0.500                                   
training_size_factortraining_800  -0.247  0.500  0.500  0.500  0.500                            
divergence                        -0.417  0.000  0.000  0.000  0.000  0.000                     
mad                               -0.681  0.000  0.000  0.000  0.000  0.000  0.263              
gap_pct                           -0.089  0.000  0.000  0.000  0.000  0.000 -0.499 -0.144       
n_loci.1000                       -0.716  0.000  0.000  0.000  0.000  0.000  0.329  0.301 -0.147

Standardized Within-Group Residuals:
        Min          Q1         Med          Q3         Max 
-1.17729607 -0.27086453 -0.03456377  0.14784375 16.22606510 

Number of Observations: 324
Number of Groups: 54 
print(intervals(model.exponential,which = "fixed"))
Approximate 95% confidence intervals

 Fixed effects:
                                       lower       est.      upper
(Intercept)                       -35178.433 -10480.679  14217.076
training_size_factortraining_1600 -34253.657 -22037.558  -9821.460
training_size_factortraining_200  -28945.529 -16729.430  -4513.332
training_size_factortraining_3200 -34613.119 -22397.020 -10180.922
training_size_factortraining_400  -33505.354 -21289.255  -9073.157
training_size_factortraining_800  -33991.002 -21774.903  -9558.805
divergence                          5609.752  10215.305  14820.858
mad                               -71953.762  -5492.677  60968.408
gap_pct                           -70215.844 -41053.240 -11890.637
n_loci.1000                         7579.053  13003.515  18427.976
attr(,"label")
[1] "Fixed effects:"
qqnorm(model.exponential, ~ranef(., level=1))

summary(glht(model=model.exponential, linfct=mcp(training_size_factor =c("training_200 - training_100 >= 0","training_400 - training_200 >= 0","training_800 - training_400 >= 0","training_1600 - training_800 >= 0","training_3200 - training_1600 >= 0")),test = adjusted(type = "bonferroni")))

     Simultaneous Tests for General Linear Hypotheses

Multiple Comparisons of Means: User-defined Contrasts


Fit: lme.formula(fixed = lasso_test_mse ~ training_size_factor + divergence + 
    mad + gap_pct + n_loci.1000, data = data_exponential, random = ~1 | 
    dataset_id)

Linear Hypotheses:
                                   Estimate Std. Error z value Pr(<z)  
training_200 - training_100 >= 0   -16729.4     6204.4  -2.696 0.0175 *
training_400 - training_200 >= 0    -4559.8     6204.4  -0.735 0.8117  
training_800 - training_400 >= 0     -485.6     6204.4  -0.078 0.9967  
training_1600 - training_800 >= 0    -262.7     6204.4  -0.042 0.9977  
training_3200 - training_1600 >= 0   -359.5     6204.4  -0.058 0.9973  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Adjusted p values reported -- single-step method)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ21kK1NoaWZ0K0VudGVyKi4gCgpgYGB7cn0KbGlicmFyeShsbWU0KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdHJpeCkKbGlicmFyeSh2aXNyZWcpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsYXNzb19vdXRwdXRfZGF0YSA8LSBkYXRhLmZyYW1lKHJlYWQuY3N2KCIvVXNlcnMvbm9hL1dvcmtzcGFjZS9sYXNzb19wb3NpdGlvbnNfc2FtcGxpbmdfcmVzdWx0cy9sc19jLmNzdiIsaGVhZGVyID0gVFJVRSwgbmEuc3RyaW5ncyA9ICIiKSkKZGF0YV9zb3VyY2UgPSBkYXRhLmZyYW1lKHJlYWQuY3N2KCIvVXNlcnMvbm9hL1dvcmtzcGFjZS9kYXRhL3NhbXBsZWRfZGF0YXNldHMuY3N2IixoZWFkZXIgPSBUUlVFLCBuYS5zdHJpbmdzID0gIiIpKQpsYXNzb19vdXRwdXRfZGF0YSRyZWxhdGl2ZV9wYXRoID0gc3RyX3JlcGxhY2VfYWxsKGxhc3NvX291dHB1dF9kYXRhJGRhdGFzZXRfaWQsJygvZ3JvdXBzL3B1cGtvL25vYWVrZXIvZGF0YS9BQkNfRFIvKXwoL3JlZl9tc2EuYWEucGh5KScsIiIpCmRhdGFfb25seV9sYXNzbz0gbWVyZ2UobGFzc29fb3V0cHV0X2RhdGEsZGF0YV9zb3VyY2UsYnkueD0icmVsYXRpdmVfcGF0aCIsYnkueT0icGF0aCIpCmlmIChucm93KGRhdGFfb25seV9sYXNzbyk8bnJvdyhsYXNzb19vdXRwdXRfZGF0YSkpCntwcmludCgiUHJvYmxlbSBpbiBtYXRjaGluZyBwYXRoIG5hbWVzIikKICBjYXQoIm5yb3cgZGF0YT0iLG5yb3coZGF0YSksICJucm93IGxhc3NvPSIsbnJvdyhkYXRhX29ubHlfbGFzc28pKQp9CgoKCiNzcHJfbmV3PC1tZXJnZShnb29kX2RhdGFzZXRzLCBzcHJfbmV3LCBieSA9ICJkYXRhc2V0X2lkIikKI3Rlc3Q8LXNwcl9uZXcgJT4lIGdyb3VwX2J5KGRhdGFzZXRfaWQpICU+JSBjb3VudChkYXRhc2V0X2lkKQpwcmludChzdW1tYXJ5KGRhdGFfb25seV9sYXNzbyRtYWQpKQpwcmludChzdW1tYXJ5KGRhdGFfb25seV9sYXNzbyRkaXZlcmdlbmNlKSkKCgpwcmludChzdW1tYXJ5KGRhdGFfb25seV9sYXNzbyRsYXNzb190ZXN0X21zZSkpCgpgYGAKCkdlbmVyYWwgc3RhdGlzdGljcyBvbiB0aGUgZGF0YQoKYGBge3J9CmZpbGVfbmFtZV9hbmRfc291cmNlX2xhc3NvPWRhdGFfb25seV9sYXNzb1shZHVwbGljYXRlZChkYXRhX29ubHlfbGFzc29bICwgYygiZGIiLCJkYXRhc2V0X2lkIildKSxdCgp0YWJsZShmaWxlX25hbWVfYW5kX3NvdXJjZV9sYXNzbyRkYikKCnByaW50KHN1bW1hcnkoZGF0YV9vbmx5X2xhc3NvJG5fbG9jaSkpCgpgYGAKCgpHb29kIGZ1bmN0aW9ucwpgYGB7cn0KcGxvdC5oaXN0PC1mdW5jdGlvbih4LG1haW4seGxhYiwgdGl0bGVfc2l6ZT0xMywgdGV4dF9zaXplPTEyKQp7CiAgcXBsb3QoeCwKICAgICAgZ2VvbT0iaGlzdG9ncmFtIiwKICAgICAgbWFpbiA9IG1haW4sIAogICAgICB4bGFiID0geGxhYiwKICAgICAgZmlsbD1JKCJibHVlIiksIAogICAgICBjb2w9SSgicmVkIiksIAogICAgICBhbHBoYT1JKC4yKSwKICAgICAgI3hsaW09YygyMCw1MCkKICAgICAgKSArICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LHNpemU9dGl0bGVfc2l6ZSkpICt0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0X3NpemUpKSAKCn0KCmxtcCA8LSBmdW5jdGlvbiAobW9kZWxvYmplY3QpIHsKICAgIGlmIChjbGFzcyhtb2RlbG9iamVjdCkgIT0gImxtIikgc3RvcCgiTm90IGFuIG9iamVjdCBvZiBjbGFzcyAnbG0nICIpCiAgICBmIDwtIHN1bW1hcnkobW9kZWxvYmplY3QpJGZzdGF0aXN0aWMKICAgIHAgPC0gcGYoZlsxXSxmWzJdLGZbM10sbG93ZXIudGFpbD1GKQogICAgYXR0cmlidXRlcyhwKSA8LSBOVUxMCiAgICByZXR1cm4ocCkKfQoKc2ltcGxlLnJlZ3Jlc3Npb248LWZ1bmN0aW9uKHgseSxtYWluLHhsYWIsIHlsYWIsY2V4PTEuMCxyZXNpZF9wbG90PUZBTFNFKQp7bGluZWFyTW9kIDwtIGxtKCh5KSB+IHgpCnByaW50KG1haW4pCnByaW50KHN1bW1hcnkobGluZWFyTW9kKSkgCnIuc3F1YXJlZCA8LSBzdW1tYXJ5KGxpbmVhck1vZCkkci5zcXVhcmVkCglwLnZhbCA8LSBsbXAobGluZWFyTW9kKQppZiAocmVzaWRfcGxvdD09VFJVRSkKe3Bsb3QoZml0dGVkKGxpbmVhck1vZCkscmVzaWQobGluZWFyTW9kKSwgbWFpbiA9bWFpbix4bGFiPXhsYWIpCmFibGluZSgwLCAwKQp9CgkKCXJldHVybihjKHIuc3F1YXJlZCxwLnZhbCkpCn0KYGBgCgpMYXNzbyBleGFtcGxlIHVzaW5nIG9wdGltaXplZCBicmFuY2ggbGVuZ3RocyBhbmQgY2hvc2VuX3NpemUgcmFuZG9tIHRyZWVzCgpgYGB7cn0KZXhhbXBsZV9NU0FfZGF0YV9sYXNzbyA9IGRhdGFfb25seV9sYXNzbyU+JWZpbHRlcihqb2JfaWQ9PTEwKQpwcmludChleGFtcGxlX01TQV9kYXRhX2xhc3NvKQoKdHJhaW5pbmdfb3B0aW1pemVkX2Nob3Nlbl9zaXplX2V4YW1wbGVfZGF0YSA9IAogIGRhdGEuZnJhbWUocmVhZC5jc3YoIi9Vc2Vycy9ub2EvV29ya3NwYWNlL2xhc3NvX3Bvc2l0aW9uc19zYW1wbGluZ19yZXN1bHRzL3RyYWluaW5nX3NpdGVsaF9kZl9wcmVkaWN0aW9uLmNzdiIsaGVhZGVyID0gVFJVRSwgbmEuc3RyaW5ncyA9ICIiKSkKbmFtZXModHJhaW5pbmdfb3B0aW1pemVkX2Nob3Nlbl9zaXplX2V4YW1wbGVfZGF0YSlbMjozXT1jKCJ0cmFpbmluZ190cnVlX3ZhbCIsInRyYWluaW5nX3ByZWRpY3RlZF92YWwiKQp0ZXN0X29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGEgPSAKICBkYXRhLmZyYW1lKHJlYWQuY3N2KCIvVXNlcnMvbm9hL1dvcmtzcGFjZS9sYXNzb19wb3NpdGlvbnNfc2FtcGxpbmdfcmVzdWx0cy90ZXN0X3NpdGVsaF9kZl9wcmVkaWN0aW9uLmNzdiIsaGVhZGVyID0gVFJVRSwgbmEuc3RyaW5ncyA9ICIiKSkKbmFtZXModGVzdF9vcHRpbWl6ZWRfY2hvc2VuX3NpemVfZXhhbXBsZV9kYXRhKVsyOjNdPWMoInRlc3RfdHJ1ZV92YWwiLCJ0ZXN0X3ByZWRpY3RlZF92YWwiKQoKCgpjaG9zZW5fc2l6ZT04MDAKZXhhbXBsZV9NU0FfZGF0YV9sYXNzb19jaG9zZW5fc2l6ZT0gZXhhbXBsZV9NU0FfZGF0YV9sYXNzbyU+JSBmaWx0ZXIoYWN0dWNhbF90cmFpbmluZ19zaXplPT1jaG9zZW5fc2l6ZSkKZXhhbXBsZV9NU0FfZGF0YV9sYXNzb19jaG9zZW5fc2l6ZV9vcHRpbWl6ZWQgPSBleGFtcGxlX01TQV9kYXRhX2xhc3NvJT4lIGZpbHRlcihhY3R1Y2FsX3RyYWluaW5nX3NpemU9PWNob3Nlbl9zaXplLCBicmxlbl9nZW5lcmF0b3I9PSJvcHRpbWl6ZWQiKQpwcmludChkcGx5cjo6c2VsZWN0KGV4YW1wbGVfTVNBX2RhdGFfbGFzc29fY2hvc2VuX3NpemUsImRhdGFzZXRfaWQiLCJicmxlbl9nZW5lcmF0b3IiLCJqb2JfaWQiLCJjdXJyX21zYV92ZXJzaW9uX2ZvbGRlciIsIm5fc2VxIiwgImRiIiwibnVtYmVyX2xvY2lfY2hvc2VuIiwibl9sb2NpIiwiYWxwaGEiLCJsYXNzb190cmFpbmluZ19SLjIiLCAibGFzc29fdGVzdF9SLjIiLCJzYW1wbGVfcGN0IiwgImxhc3NvX3RyYWluaW5nX3NwZWFybWFuciIsICJsYXNzb190ZXN0X3NwZWFybWFuciIpKQoKcHJpbnQoZHBseXI6OnNlbGVjdChleGFtcGxlX01TQV9kYXRhX2xhc3NvX2Nob3Nlbl9zaXplX29wdGltaXplZCwiZGF0YXNldF9pZCIsImpvYl9pZCIsImN1cnJfbXNhX3ZlcnNpb25fZm9sZGVyIiwibl9zZXEiLCAiZGIiLCJudW1iZXJfbG9jaV9jaG9zZW4iLCJuX2xvY2kiLCJhbHBoYSIsImxhc3NvX3RyYWluaW5nX1IuMiIsICJsYXNzb190ZXN0X1IuMiIsInNhbXBsZV9wY3QiLCAibGFzc29fdHJhaW5pbmdfc3BlYXJtYW5yIiwgImxhc3NvX3Rlc3Rfc3BlYXJtYW5yIikpCnRyYWluaW5nX29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbInRyYWluaW5nIGRlbHRhIGxsIl0gPXRyYWluaW5nX29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbInRyYWluaW5nX3RydWVfdmFsIl0tdHJhaW5pbmdfb3B0aW1pemVkX2Nob3Nlbl9zaXplX2V4YW1wbGVfZGF0YVsidHJhaW5pbmdfcHJlZGljdGVkX3ZhbCJdCnRlc3Rfb3B0aW1pemVkX2Nob3Nlbl9zaXplX2V4YW1wbGVfZGF0YVsidGVzdCBkZWx0YSBsbCJdID10ZXN0X29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbInRlc3RfdHJ1ZV92YWwiXS10ZXN0X29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbInRlc3RfcHJlZGljdGVkX3ZhbCJdCnByaW50KHRyYWluaW5nX29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbLGMoInRyYWluaW5nX3ByZWRpY3RlZF92YWwiLCJ0cmFpbmluZ190cnVlX3ZhbCIsInRyYWluaW5nIGRlbHRhIGxsIildKQpwcmludCh0ZXN0X29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbLGMoInRlc3RfcHJlZGljdGVkX3ZhbCIsInRlc3RfdHJ1ZV92YWwiLCJ0ZXN0IGRlbHRhIGxsIildKQoKcDA8LXNpbXBsZS5yZWdyZXNzaW9uKHRyYWluaW5nX29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGEkdHJhaW5pbmdfdHJ1ZV92YWwsdHJhaW5pbmdfb3B0aW1pemVkX2Nob3Nlbl9zaXplX2V4YW1wbGVfZGF0YSR0cmFpbmluZ19wcmVkaWN0ZWRfdmFsLCJUcmFpbmluZyBzZXQgcHJlZGljdGVkIGxvZyBsaWtlbGlob29kIHZzIHRydWUgbG9nIGxpa2VsaWhvb2QiLCJUcmFpbmluZyBzZXQgdHJ1ZSBsb2cgbGlrZWxpaG9vZCIsIlRyYWluaW5nIHNldCBwcmVkaWN0ZWQgbG9nIGxpa2VsaWhvb2QiKQpwMTwtc2ltcGxlLnJlZ3Jlc3Npb24odGVzdF9vcHRpbWl6ZWRfY2hvc2VuX3NpemVfZXhhbXBsZV9kYXRhJHRlc3RfdHJ1ZV92YWwsdGVzdF9vcHRpbWl6ZWRfY2hvc2VuX3NpemVfZXhhbXBsZV9kYXRhJHRlc3RfcHJlZGljdGVkX3ZhbCwiVGVzdCBzZXQgcHJlZGljdGVkIGxvZyBsaWtlbGlob29kIHZzIHRydWUgbG9nIGxpa2VsaWhvb2QiLCJUZXN0IHNldCB0cnVlIGxvZyBsaWtlbGlob29kIiwiVGVzdCBzZXQgcHJlZGljdGVkIGxvZyBsaWtlbGlob29kIixjZXg9MSkKCgoKZzA8LWdncGxvdCh0cmFpbmluZ19vcHRpbWl6ZWRfY2hvc2VuX3NpemVfZXhhbXBsZV9kYXRhLGFlcyh0cmFpbmluZ190cnVlX3ZhbCwgdHJhaW5pbmdfcHJlZGljdGVkX3ZhbCkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSdsbScpK3hsYWIoInRydWUgbG9nIGxpa2VsaWhvb2QiKSt5bGFiKCJwcmVkaWN0ZWQgbG9nIGxpa2VsaWhvb2QgIikrZ2VvbV9wb2ludCgpKyBsYWJzKHRpdGxlPSJUcmFpbmluZyBzZXQgcHJlZGljdGVkIGxvZyBsaWtlbGlob29kIHZzIHRydWUgbG9nIGxpa2VsaWhvb2QiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgK2Fubm90YXRlKCJ0ZXh0IiwgeD0tMjAzMDAsIHk9LTE5ODAwLCBsYWJlbD0gc3ByaW50ZigiUl4yID0gJS40ZiIscDBbMV0pLHNpemU9NCkgK2Fubm90YXRlKCJ0ZXh0IiwgeD0tMjAzMDAsIHk9LTE5OTUwLCBsYWJlbD0gInAgdmFsdWUgPCAyZS0zMjQiLHNpemU9NCkgCgpnMTwtZ2dwbG90KHRlc3Rfb3B0aW1pemVkX2Nob3Nlbl9zaXplX2V4YW1wbGVfZGF0YSxhZXModGVzdF90cnVlX3ZhbCwgdGVzdF9wcmVkaWN0ZWRfdmFsKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9J2xtJykreGxhYigidHJ1ZSBsb2cgbGlrZWxpaG9vZCIpK3lsYWIoInByZWRpY3RlZCBsb2cgbGlrZWxpaG9vZCAiKStnZW9tX3BvaW50KCkrIGxhYnModGl0bGU9IlRlc3Qgc2V0IHByZWRpY3RlZCBsb2cgbGlrZWxpaG9vZCB2cyB0cnVlIGxvZyBsaWtlbGlob29kIikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICthbm5vdGF0ZSgidGV4dCIsIHg9LTIwMzAwLCB5PS0xOTgwMCwgbGFiZWw9IHNwcmludGYoIlJeMiA9ICUuNGYiLHAxWzFdKSkgK2Fubm90YXRlKCJ0ZXh0IiwgeD0tMjAzMDAsIHk9LTE5OTUwLCBsYWJlbD0gc3ByaW50ZigicCB2YWx1ZSA9ICUuMmUiLHAxWzJdKSkgCgoKZmlnPC1nZ2FycmFuZ2UoZzAsIGcxLCBoanVzdD0tMSx2anVzdD0xLCBoZWlnaHRzPWMoMiwyKSxjb21tb24ubGVnZW5kPVRSVUUsIAogICAgICAgICAgbGFiZWxzID0gYygiQSIsICJCIiksCiAgICAgICAgICBuY29sID0gMSwgbnJvdyA9MikKCmZpZwoKCgoKYGBgCgpgYGB7cn0KYm94cGxvdCh0ZXN0X29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbInRlc3QgZGVsdGEgbGwiXSkKc3VtbWFyeSh0ZXN0X29wdGltaXplZF9jaG9zZW5fc2l6ZV9leGFtcGxlX2RhdGFbInRlc3QgZGVsdGEgbGwiXSkKcHJpbnQodGVzdF9vcHRpbWl6ZWRfY2hvc2VuX3NpemVfZXhhbXBsZV9kYXRhKQoKYGBgCgoKTGFzc28gcHJvYmxlbWF0aWMgZGF0YXNldHMKYGBge3J9CnByaW50KCBkYXRhX29ubHlfbGFzc29bZGF0YV9vbmx5X2xhc3NvJGxhc3NvX3Rlc3RfUi4yPDAuOSxjKCJicmxlbl9nZW5lcmF0b3IiLCJhY3R1Y2FsX3RyYWluaW5nX3NpemUiLCJuX3NlcSIsIm5fbG9jaSIsInNhbXBsZV9wY3QiLCJsYXNzb190ZXN0X1IuMiIsICJsYXNzb190cmFpbmluZ19SLjIiLCAibGFzc29fdHJhaW5pbmdfc3BlYXJtYW5yIiwibnVtYmVyX2xvY2lfY2hvc2VuIildKQoKYGBgCgpFeGFtcGxlIE1TQSBMYXNzbyBzdGF0aXN0aWNzCmBgYHtyfQpsaWJyYXJ5KGdncHVicikKCmRwbHlyOjpzZWxlY3QoZXhhbXBsZV9NU0FfZGF0YV9sYXNzbyxhY3R1Y2FsX3RyYWluaW5nX3NpemUsYnJsZW5fZ2VuZXJhdG9yLGxhc3NvX3Rlc3RfUi4yLGxhc3NvX3Rlc3Rfc3BlYXJtYW5yLHNhbXBsZV9wY3QsbnVtYmVyX2xvY2lfY2hvc2VuKQpkcGx5cjo6c2VsZWN0KGV4YW1wbGVfTVNBX2RhdGFfbGFzc28lPiVmaWx0ZXIoYWN0dWNhbF90cmFpbmluZ19zaXplPT1jaG9zZW5fc2l6ZSksYWN0dWNhbF90cmFpbmluZ19zaXplLGJybGVuX2dlbmVyYXRvcixsYXNzb190ZXN0X1IuMixsYXNzb190ZXN0X3NwZWFybWFucixzYW1wbGVfcGN0LG51bWJlcl9sb2NpX2Nob3NlbikKCgpnMDwtZ2dwbG90KGV4YW1wbGVfTVNBX2RhdGFfbGFzc28sIGFlcyh4PWFzLmZhY3RvcihhY3R1Y2FsX3RyYWluaW5nX3NpemUpLGZpbGw9YnJsZW5fZ2VuZXJhdG9yLCB5PWxhc3NvX3Rlc3RfUi4yKSkrCiAgICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCkpICsKICB4bGFiKCJUcmFpbmluZyBzaXplIikreWxhYigiUiBzcXVhcmVkICIpK3RoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKStndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IkJyYW5jaCBsZW5ndGggZGlzdHJpYnV0aW9uIikpK2dndGl0bGUoIlRlc3Qgc2V0IFIgc3F1YXJlZCB2cy4gdHJhaW5pbmcgc2l6ZSIpKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgK2Nvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLjU1LCAxKSkKCgpnZ3Bsb3QoZXhhbXBsZV9NU0FfZGF0YV9sYXNzbywgYWVzKHg9YXMuZmFjdG9yKGFjdHVjYWxfdHJhaW5pbmdfc2l6ZSksZmlsbD1icmxlbl9nZW5lcmF0b3IsIHk9ZXhhbXBsZV9NU0FfZGF0YV9sYXNzbyRsYXNzb190ZXN0X21zZSkpKwogICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgpKSArCiAgeGxhYigiVHJhaW5pbmcgc2l6ZSIpK3lsYWIoIk1TRSAiKSt0aGVtZShheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkrZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJCcmFuY2ggbGVuZ3RoIGRpc3RyaWJ1dGlvbiIpKStnZ3RpdGxlKCJUZXN0IHNldCBSIHNxdWFyZWQgdnMuIHRyYWluaW5nIHNpemUiKSsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgoKIGcyPC1nZ3Bsb3QoZXhhbXBsZV9NU0FfZGF0YV9sYXNzbywgYWVzKHg9YXMuZmFjdG9yKGFjdHVjYWxfdHJhaW5pbmdfc2l6ZSksZmlsbD1icmxlbl9nZW5lcmF0b3IsIHk9c2FtcGxlX3BjdCkpKyBsYWJzKGNvbG9yID0gIkJyYW5jaCBsZW5ndGggZGlzdHJpYnV0aW9uIikrCiAgICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCkpICsKICAgeGxhYigiVHJhaW5pbmcgc2l6ZSIpK3lsYWIoIiUgUG9zaXRpb25zIikrIHRoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApLCkrZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJCcmFuY2ggbGVuZ3RoIGRpc3RyaWJ1dGlvbiIpKStnZ3RpdGxlKCJQZXJjZW50YWdlIG9mIHBvc2l0aW9ucyBjaG9zZW4gYnkgTGFzc28gdnMuIHRyYWluaW5nIHNpemUiICkrc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkrIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAKCmdnYXJyYW5nZShnMCwgZzIsIGhqdXN0PS0xLHZqdXN0PTAsIGhlaWdodHM9YygyLDIpLGNvbW1vbi5sZWdlbmQ9VFJVRSwgCiAgICAgICAgICBsYWJlbHMgPSBjKCJBIiwgIkIiKSwKICAgICAgICAgIG5jb2wgPSAxLCBucm93ID0yKQoKCnBsb3QoZXhhbXBsZV9NU0FfZGF0YV9sYXNzbyRsYXNzb190ZXN0X21zZSwgZXhhbXBsZV9NU0FfZGF0YV9sYXNzbyRsYXNzb190ZXN0X1IuMikKCgoKIAoKYGBgCmBgYHtyfQpwcmludChleGFtcGxlX01TQV9kYXRhX2xhc3NvWyxjKCJicmxlbl9nZW5lcmF0b3IiLCJuX2xvY2kiLCJudW1iZXJfbG9jaV9jaG9zZW4iKV0pCmBgYApgYGB7cn0KbGFzc29fb3B0aW1pemVkXzgwMDwtIGZpbHRlcihkYXRhX29ubHlfbGFzc28KbGFzc29fdW5pcXVlPC11bmlxdWUoZHBseXI6OnNlbGVjdChkYXRhX29ubHlfbGFzc28sZGF0YXNldF9pZCxuX2xvY2ksc2FtcGxlX3BjdCkpCnBsb3QobGFzc29fdW5pcXVlJG5fbG9jaSxsYXNzb191bmlxdWUkc2FtcGxlX3BjdCApCmBgYAoKCkZpZ3VyZSA2IC0gTGFzc28gb24gNTAgTVNBcyBvbmx5IDMyMDAKYGBge3J9CgpjaG9zZW5fc2l6ZSA9IDMyMDAKZGF0YV9sYXNzb19vbmx5X2Nob3Nlbl9zaXplID0gZGF0YV9vbmx5X2xhc3NvW2RhdGFfb25seV9sYXNzbyRhY3R1Y2FsX3RyYWluaW5nX3NpemU9PWNob3Nlbl9zaXplLF0KCmxhc3NvLmNob3Nlbl9zaXplLnN1bW1hcnkgPSBkYXRhX2xhc3NvX29ubHlfY2hvc2VuX3NpemUgJT4lCmdyb3VwX2J5KCkgJT4lCnN1bW1hcmlzZShhY3Jvc3MoLmNvbHM9YyhsYXNzb190ZXN0X1IuMixsYXNzb190ZXN0X3NwZWFybWFucixzYW1wbGVfcGN0KSwgLmZucz0gbGlzdChNZWRpYW49bWVkaWFuKSwgbmEucm09IFRSVUUpLC5ncm91cHMgPSAiZHJvcCIpCgpwcmludChsYXNzby5jaG9zZW5fc2l6ZS5zdW1tYXJ5KQoKbGFzc28uY2hvc2VuX3NpemUuc3VtbWFyeS5wZXIuYnJsZW4gPSBkYXRhX2xhc3NvX29ubHlfY2hvc2VuX3NpemUgJT4lCmdyb3VwX2J5KGFjdHVjYWxfdHJhaW5pbmdfc2l6ZSxicmxlbl9nZW5lcmF0b3IgKSAlPiUKc3VtbWFyaXNlKGFjcm9zcyguY29scz1jKGxhc3NvX3Rlc3RfUi4yLGxhc3NvX3Rlc3Rfc3BlYXJtYW5yLHNhbXBsZV9wY3QpLCAuZm5zPSBsaXN0KE1lZGlhbj1tZWRpYW4pLCBuYS5ybT0gVFJVRSksLmdyb3VwcyA9ICJkcm9wIikKcHJpbnQobGFzc28uY2hvc2VuX3NpemUuc3VtbWFyeS5wZXIuYnJsZW4pCiAgICAKICAgIAojRmlndXJlIDYKZzA8LWdncGxvdChkYXRhX2xhc3NvX29ubHlfY2hvc2VuX3NpemUsYWVzKGxhc3NvX3Rlc3RfUi4yLGZpbGw9YnJsZW5fZ2VuZXJhdG9yKSkrIAogICAgIGdlb21faGlzdG9ncmFtKCkrCiAgICBsYWJzKHRpdGxlPSJMYXNzbyB0ZXN0IHNldCBQZWFyc29uIFIgc3F1YXJlZCIpK3hsYWIoIlBlYXJzb24gUiBzcXVhcmVkIikrIGxhYnMoZmlsbD0gIkJyYW5jaCBsZW5ndGggZGlzdHJpYnV0aW9uIikrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpIApnMjwtIGdncGxvdChkYXRhX2xhc3NvX29ubHlfY2hvc2VuX3NpemUsYWVzKHNhbXBsZV9wY3QsZmlsbD1icmxlbl9nZW5lcmF0b3IpKSsgCiAgICAgZ2VvbV9oaXN0b2dyYW0oKSsKICAgIGxhYnModGl0bGU9IlBlcmNlbnRhZ2Ugb2YgcG9zaXRpb25zIGNob3NlbiBieSBMYXNzbyIpK3hsYWIoIiUgcG9zaXRpb25zIikrIGxhYnMoZmlsbCA9ICJCcmFuY2ggbGVuZ3RoIGRpc3RyaWJ1dGlvbiIpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIAoKCgpnZ2FycmFuZ2UoZzAsIGcyLGhqdXN0PS0xLHZqdXN0PTAsY29tbW9uLmxlZ2VuZD1UUlVFLGFsaWduPSJoIiwKICAgICAgICAgIGxhYmVscyA9IGMoIkEiLCAiQiIpLAogICAgICAgICAgbmNvbCA9IDEsIG5yb3cgPTIpCgoKCiAgICAKCmBgYAoKCkZpZ3VyZSA0IG9yIHRhYmxlMiAtIHJlc3VsdHMgb24gNTAgTVNBcwoKYGBge3J9CgpwZXIuYnJsZW4uc2l6ZSA9IGRwbHlyOjpzZWxlY3QoZGF0YV9vbmx5X2xhc3NvLGFjdHVjYWxfdHJhaW5pbmdfc2l6ZSxicmxlbl9nZW5lcmF0b3IsbGFzc29fdGVzdF9SLjIsc2FtcGxlX3BjdCkgJT4lCmdyb3VwX2J5KGFjdHVjYWxfdHJhaW5pbmdfc2l6ZSxicmxlbl9nZW5lcmF0b3IpICU+JQpzdW1tYXJpc2UoYWNyb3NzKC5mbnM9IGxpc3QoTWVkaWFuPW1lZGlhbiksIG5hLnJtPSBUUlVFKSwuZ3JvdXBzID0gImRyb3AiKQpwcmludChwZXIuYnJsZW4uc2l6ZSkKCgpwZXIuYnJsZW4uc2l6ZS5tc2UgPSBkcGx5cjo6c2VsZWN0KGRhdGFfb25seV9sYXNzbyxsYXNzb190ZXN0X21zZSxhY3R1Y2FsX3RyYWluaW5nX3NpemUsYnJsZW5fZ2VuZXJhdG9yKSAlPiUKZ3JvdXBfYnkoYWN0dWNhbF90cmFpbmluZ19zaXplLGJybGVuX2dlbmVyYXRvcikgJT4lCnN1bW1hcmlzZShhY3Jvc3MoLmZucz0gbGlzdChNZWRpYW49bWVkaWFuKSwgbmEucm09IFRSVUUpLC5ncm91cHMgPSAiZHJvcCIpCnByaW50KHBlci5icmxlbi5zaXplLm1zZSApCgpvcHRpbWl6ZWRfbXNlID0gZmlsdGVyKHBlci5icmxlbi5zaXplLm1zZSwgYnJsZW5fZ2VuZXJhdG9yPT0ib3B0aW1pemVkIikKb3B0aW1pemVkX1IyPWZpbHRlcihwZXIuYnJsZW4uc2l6ZSwgYnJsZW5fZ2VuZXJhdG9yPT0ib3B0aW1pemVkIikKCnBsb3Qob3B0aW1pemVkX21zZSRhY3R1Y2FsX3RyYWluaW5nX3NpemUsIG9wdGltaXplZF9tc2UkbGFzc29fdGVzdF9tc2VfTWVkaWFuLHR5cGU9ImIiLCB4bGFiPSJUcmFpbmluZyBzaXplIiwgeWxhYiA9Ik1lZGlhbiB0ZXN0IE1TRSIsdGl0bGU9Ik1lZGlhbiB0ZXN0IE1TRSB2cy4gdHJhaW5pbmcgc2l6ZSBmb3Igb3B0aW1pemVkIGJyYW5jaC1sZW5ndGgiKQoKZzAwPC1nZ3Bsb3Qob3B0aW1pemVkX21zZSxhZXMoeD1hY3R1Y2FsX3RyYWluaW5nX3NpemUseT1sYXNzb190ZXN0X21zZV9NZWRpYW4pKStnZW9tX2xpbmUoKStnZW9tX3BvaW50KGRhdGE9b3B0aW1pemVkX21zZSxhZXMoeD1hY3R1Y2FsX3RyYWluaW5nX3NpemUseT1sYXNzb190ZXN0X21zZV9NZWRpYW4pKSt4bGFiKCJUcmFpbmluZyBzaXplIikreWxhYigiTWVkaWFuIHRlc3QgTVNFIikrZ2d0aXRsZSgiTWVkaWFuIHRlc3QgTVNFIHZzLiB0cmFpbmluZyBzaXplIGZvciBvcHRpbWl6ZWQgYnJhbmNoLWxlbmd0aHMiKSsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTExKSxheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTExKQopIAoKZzAxPC1nZ3Bsb3Qob3B0aW1pemVkX1IyZSxhZXMoeD1hY3R1Y2FsX3RyYWluaW5nX3NpemUseT1sYXNzb190ZXN0X1IuMl9NZWRpYW4pKStnZW9tX2xpbmUoKStnZW9tX3BvaW50KGRhdGE9b3B0aW1pemVkX1IyLGFlcyh4PWFjdHVjYWxfdHJhaW5pbmdfc2l6ZSx5PWxhc3NvX3Rlc3RfUi4yX01lZGlhbikpK3hsYWIoIlRyYWluaW5nIHNpemUiKSt5bGFiKCJNZWRpYW4gdGVzdCBSMiIpK2dndGl0bGUoIk1lZGlhbiB0ZXN0IE1TRSB2cy4gdHJhaW5pbmcgc2l6ZSBmb3Igb3B0aW1pemVkIGJyYW5jaC1sZW5ndGhzIikrIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMSksYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMSkKCmcwMQoKCgoKZzA8LWdncGxvdChkYXRhX29ubHlfbGFzc28sYWVzKHg9YXMuZmFjdG9yKGFjdHVjYWxfdHJhaW5pbmdfc2l6ZSksY29sb3I9YnJsZW5fZ2VuZXJhdG9yLCB5PWxhc3NvX3Rlc3RfUi4yKSkrIAogICAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSsjdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMCksKSsKICAgIGxhYnModGl0bGU9InRlc3QgUiBzcXVhcmVkIikreGxhYigiVHJhaW5pbmcgc2l6ZSIpKyB5bGFiKCJSIHNxdWFyZWQiKSsgbGFicyhjb2xvciA9ICJCcmFuY2ggbGVuZ3RoIGRpc3RyaWJ1dGlvbiIpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSt0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIpK2Nvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLjYsIDEpKQoKZzI8LWdncGxvdChkYXRhX29ubHlfbGFzc28sIGFlcyh4PWFzLmZhY3RvcihhY3R1Y2FsX3RyYWluaW5nX3NpemUpLGNvbG9yPWJybGVuX2dlbmVyYXRvciwgeT1zYW1wbGVfcGN0KSkrIGxhYnMoY29sb3IgPSAiQnJhbmNoIGxlbmd0aCBkaXN0cmlidXRpb24iKSsKICAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZT1OQSkgKwogICB4bGFiKCJUcmFpbmluZyBzaXplIikreWxhYigiJXBvc2l0aW9ucyIpKyAjdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMCksKQogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT0iQnJhbmNoIGxlbmd0aCBkaXN0cmlidXRpb24iKSkrZ2d0aXRsZSgiUGVyY2VudGFnZSBvZiBwb3NpdGlvbnMgY2hvc2VuIGJ5IExhc3NvIikrc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkrIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikrIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAKCiNnZ2FycmFuZ2UoZzAsIGcxLGhqdXN0PS0xLHZqdXN0PTEsIGNvbW1vbi5sZWdlbmQ9VFJVRSwKIyAgICAgICAgICBsYWJlbHMgPSBjKCJBIiwgIkIiKSwKIyAgICAgICAgICBuY29sID0gMSwgbnJvdyA9MikKCmdnYXJyYW5nZShnMCwgZzIsIGhqdXN0PS0xLHZqdXN0PTEsIGNvbW1vbi5sZWdlbmQ9VFJVRSwKICAgICAgICAgIGxhYmVscyA9IGMoIkEiLCAiQiIpLAogICAgICAgICAgbmNvbCA9IDEsIG5yb3cgPTIpCgoKCgoKCmBgYAoKCgpTdGF0aXN0aWNhbCBhbmFseXNpcyBvZiB0ZXN0IE1TRSB2cyB0cmFpbmluZyBzaXplIGFuZCBNU0EgbWV0cmljcwoKYGBge3J9CmxpYnJhcnkocnN0YXRpeCkKbGlicmFyeShubG1lKQpsaWJyYXJ5KG11bHRjb21wKQoKCmRhdGFfb25seV9sYXNzbyR0cmFpbmluZ19zaXplX2ZhY3RvciA9IGFzLmZhY3RvcihkYXRhX29ubHlfbGFzc28kYWN0dWNhbF90cmFpbmluZ19zaXplKQpkYXRhX29ubHlfbGFzc28kbl9sb2NpLjEwMDA9ZGF0YV9vbmx5X2xhc3NvJG5fbG9jaS8xMDAwCmRhdGFfZXhwb25lbnRpYWw8LWRhdGFfb25seV9sYXNzbyAlPiUgZmlsdGVyKGJybGVuX2dlbmVyYXRvcj09ImV4cG9uZW50aWFsIikKZGF0YV9vcHRpbWl6ZWQ8LWRhdGFfb25seV9sYXNzbyAlPiUgZmlsdGVyKGJybGVuX2dlbmVyYXRvcj09Im9wdGltaXplZCIpCmRhdGFfdW5pZm9ybTwtZGF0YV9vbmx5X2xhc3NvICU+JSBmaWx0ZXIoYnJsZW5fZ2VuZXJhdG9yPT0idW5pZm9ybSIpCgoKCmBgYAoKYGBge3J9Cm1vZGVsPC1sbWUobGFzc29fdGVzdF9tc2V+dHJhaW5pbmdfc2l6ZV9mYWN0b3IrZGl2ZXJnZW5jZSttYWQrZ2FwX3BjdCtuX2xvY2kuMTAwMCxyYW5kb209fjF8ZGF0YXNldF9pZCwgZGF0YT1kYXRhX3VuaWZvcm0pCnBsb3QobW9kZWwudW5pZm9ybSkKcXFub3JtKG1vZGVsLnVuaWZvcm0kcmVzaWR1YWxzKQpwcmludChzdW1tYXJ5KG1vZGVsLnVuaWZvcm0pKQpwcmludChpbnRlcnZhbHMobW9kZWwudW5pZm9ybSx3aGljaCA9ICJmaXhlZCIpKQpzdW1tYXJ5KGdsaHQobW9kZWw9bW9kZWwudW5pZm9ybSwgbGluZmN0PW1jcCh0cmFpbmluZ19zaXplX2ZhY3RvciA9YygidHJhaW5pbmdfMjAwIC0gdHJhaW5pbmdfMTAwID49IDAiLCJ0cmFpbmluZ180MDAgLSB0cmFpbmluZ18yMDAgPj0gMCIsInRyYWluaW5nXzgwMCAtIHRyYWluaW5nXzQwMCA+PSAwIiwidHJhaW5pbmdfMTYwMCAtIHRyYWluaW5nXzgwMCA+PSAwIiwidHJhaW5pbmdfMzIwMCAtIHRyYWluaW5nXzE2MDAgPj0gMCIpKSx0ZXN0ID0gYWRqdXN0ZWQodHlwZSA9ICJib25mZXJyb25pIikpKQoKCmBgYAoKCgoKCnVuaWZvcm0KYGBge3J9CmRhdGFfdW5pZm9ybTwtZGF0YV9vbmx5X2xhc3NvICU+JSBmaWx0ZXIoYnJsZW5fZ2VuZXJhdG9yPT0idW5pZm9ybSIpCmRhdGFfdW5pZm9ybSR0cmFpbmluZ19zaXplX2ZhY3RvciA9IGFzLmZhY3RvcihwYXN0ZSgndHJhaW5pbmdfJywgZGF0YV91bmlmb3JtJHRyYWluaW5nX3NpemVfZmFjdG9yLHNlcCA9ICIiKSkKbW9kZWwudW5pZm9ybTwtbG1lKGxhc3NvX3Rlc3RfbXNlfnRyYWluaW5nX3NpemVfZmFjdG9yK2RpdmVyZ2VuY2UrbWFkK2dhcF9wY3Qrbl9sb2NpLjEwMDAscmFuZG9tPX4xfGRhdGFzZXRfaWQsIGRhdGE9ZGF0YV91bmlmb3JtKQpwbG90KG1vZGVsLnVuaWZvcm0pCnFxbm9ybShtb2RlbC51bmlmb3JtJHJlc2lkdWFscykKcHJpbnQoc3VtbWFyeShtb2RlbC51bmlmb3JtKSkKcHJpbnQoaW50ZXJ2YWxzKG1vZGVsLnVuaWZvcm0sd2hpY2ggPSAiZml4ZWQiKSkKc3VtbWFyeShnbGh0KG1vZGVsPW1vZGVsLnVuaWZvcm0sIGxpbmZjdD1tY3AodHJhaW5pbmdfc2l6ZV9mYWN0b3IgPWMoInRyYWluaW5nXzIwMCAtIHRyYWluaW5nXzEwMCA+PSAwIiwidHJhaW5pbmdfNDAwIC0gdHJhaW5pbmdfMjAwID49IDAiLCJ0cmFpbmluZ184MDAgLSB0cmFpbmluZ180MDAgPj0gMCIsInRyYWluaW5nXzE2MDAgLSB0cmFpbmluZ184MDAgPj0gMCIsInRyYWluaW5nXzMyMDAgLSB0cmFpbmluZ18xNjAwID49IDAiKSksdGVzdCA9IGFkanVzdGVkKHR5cGUgPSAiYm9uZmVycm9uaSIpKSkKCgpgYGAKCmBgYHtyfQpwbG90KGRhdGFfb25seV9sYXNzbyRuX2xvY2ksZGF0YV9vbmx5X2xhc3NvJGxhc3NvX3Rlc3RfbXNlKiowLjUpCmhpc3QoZGF0YV9vbmx5X2xhc3NvW2RhdGFfb25seV9sYXNzbyRicmxlbl9nZW5lcmF0b3I9PSJleHBvbmVudGlhbCIsXSRsYXNzb190ZXN0X21zZSwgYnJlYWtzPTEwMCkKYm94cGxvdChkYXRhX29ubHlfbGFzc29bZGF0YV9vbmx5X2xhc3NvJGJybGVuX2dlbmVyYXRvcj09ImV4cG9uZW50aWFsIixdJGxhc3NvX3Rlc3RfbXNlKQpwcmludChzdW1tYXJ5KGRhdGFfb25seV9sYXNzb1tkYXRhX29ubHlfbGFzc28kYnJsZW5fZ2VuZXJhdG9yPT0iZXhwb25lbnRpYWwiICYgZGF0YV9vbmx5X2xhc3NvJGFjdHVjYWxfdHJhaW5pbmdfc2l6ZT09MzIwMCxdJGxhc3NvX3Rlc3RfbXNlKSkKcHJpbnQoc3VtbWFyeShkYXRhX29ubHlfbGFzc29bZGF0YV9vbmx5X2xhc3NvJGJybGVuX2dlbmVyYXRvcj09ImV4cG9uZW50aWFsIiAmIGRhdGFfb25seV9sYXNzbyRhY3R1Y2FsX3RyYWluaW5nX3NpemU9PTMyMDAsXSRsYXNzb190ZXN0X1IuMikpCmBgYAoKCm9wdGltaXplZApgYGB7cn0KZGF0YV9vcHRpbWl6ZWQ8LWRhdGFfb25seV9sYXNzbyAlPiUgZmlsdGVyKGJybGVuX2dlbmVyYXRvcj09Im9wdGltaXplZCIpCmRhdGFfb3B0aW1pemVkJHRyYWluaW5nX3NpemVfZmFjdG9yID0gYXMuZmFjdG9yKHBhc3RlKCd0cmFpbmluZ18nLCBkYXRhX29wdGltaXplZCR0cmFpbmluZ19zaXplX2ZhY3RvcixzZXAgPSAiIikpCm1vZGVsLm9wdGltaXplZDwtbG1lKGxhc3NvX3Rlc3RfbXNlfnRyYWluaW5nX3NpemVfZmFjdG9yK2RpdmVyZ2VuY2UrbWFkK2dhcF9wY3Qrbl9sb2NpLjEwMDAscmFuZG9tPX4xfGRhdGFzZXRfaWQsIGRhdGE9ZGF0YV9vcHRpbWl6ZWQpCnByaW50KHN1bW1hcnkobW9kZWwub3B0aW1pemVkKSkKcGxvdChtb2RlbC5vcHRpbWl6ZWQpCnByaW50KGludGVydmFscyhtb2RlbC5vcHRpbWl6ZWQsd2hpY2ggPSAiZml4ZWQiKSkKc3VtbWFyeShnbGh0KG1vZGVsPW1vZGVsLm9wdGltaXplZCwgbGluZmN0PW1jcCh0cmFpbmluZ19zaXplX2ZhY3RvciA9YygidHJhaW5pbmdfMjAwIC0gdHJhaW5pbmdfMTAwID49IDAiLCJ0cmFpbmluZ180MDAgLSB0cmFpbmluZ18yMDAgPj0gMCIsInRyYWluaW5nXzgwMCAtIHRyYWluaW5nXzQwMCA+PSAwIiwidHJhaW5pbmdfMTYwMCAtIHRyYWluaW5nXzgwMCA+PSAwIiwidHJhaW5pbmdfMzIwMCAtIHRyYWluaW5nXzE2MDAgPj0gMCIpKSx0ZXN0ID0gYWRqdXN0ZWQodHlwZSA9ICJib25mZXJyb25pIikpKQoKYGBgCgpleHBvbmVudGlhbApgYGB7cn0KZGF0YV9leHBvbmVudGlhbDwtZGF0YV9vbmx5X2xhc3NvICU+JSBmaWx0ZXIoYnJsZW5fZ2VuZXJhdG9yPT0iZXhwb25lbnRpYWwiKQpkYXRhX2V4cG9uZW50aWFsJHRyYWluaW5nX3NpemVfZmFjdG9yID0gYXMuZmFjdG9yKHBhc3RlKCd0cmFpbmluZ18nLCBkYXRhX2V4cG9uZW50aWFsJHRyYWluaW5nX3NpemVfZmFjdG9yLHNlcCA9ICIiKSkKbW9kZWwuZXhwb25lbnRpYWw8LWxtZShsYXNzb190ZXN0X21zZX50cmFpbmluZ19zaXplX2ZhY3RvcitkaXZlcmdlbmNlK21hZCtnYXBfcGN0K25fbG9jaS4xMDAwLHJhbmRvbT1+MXxkYXRhc2V0X2lkLCBkYXRhPWRhdGFfZXhwb25lbnRpYWwpCnBsb3QobW9kZWwuZXhwb25lbnRpYWwpCnByaW50KHN1bW1hcnkobW9kZWwuZXhwb25lbnRpYWwpKQpwcmludChpbnRlcnZhbHMobW9kZWwuZXhwb25lbnRpYWwsd2hpY2ggPSAiZml4ZWQiKSkKcXFub3JtKG1vZGVsLmV4cG9uZW50aWFsLCB+cmFuZWYoLiwgbGV2ZWw9MSkpCnN1bW1hcnkoZ2xodChtb2RlbD1tb2RlbC5leHBvbmVudGlhbCwgbGluZmN0PW1jcCh0cmFpbmluZ19zaXplX2ZhY3RvciA9YygidHJhaW5pbmdfMjAwIC0gdHJhaW5pbmdfMTAwID49IDAiLCJ0cmFpbmluZ180MDAgLSB0cmFpbmluZ18yMDAgPj0gMCIsInRyYWluaW5nXzgwMCAtIHRyYWluaW5nXzQwMCA+PSAwIiwidHJhaW5pbmdfMTYwMCAtIHRyYWluaW5nXzgwMCA+PSAwIiwidHJhaW5pbmdfMzIwMCAtIHRyYWluaW5nXzE2MDAgPj0gMCIpKSx0ZXN0ID0gYWRqdXN0ZWQodHlwZSA9ICJib25mZXJyb25pIikpKQpgYGAKCg==